const { customRequire } = require('./utils.js');
const { Page } = customRequire('playwright');

// 定义日志函数，如果sendLogToRenderer模块不存在，则使用console.log作为备选
let sendLogToRenderer;
try {
    sendLogToRenderer = require('./sendLogToRenderer').sendLogToRenderer;
} catch (error) {
    // 如果模块不存在，创建一个简单的日志函数
    sendLogToRenderer = (message, type = 'info') => {
        const prefix = type === 'error' ? '[错误]' : 
                      type === 'warning' ? '[警告]' : 
                      '[信息]';
        console.log(`${prefix} ${message}`);
    };
}

/**
 * 通用重试方法，用于执行指定的异步操作
 * @param {Page} page - Playwright 的 Page 对象，代表浏览器中的一个页面，用于执行页面操作
 * @param {any} context - 上下文对象
 * @param {Function} action - 要执行的异步操作
 * @param {string} [actionName] - 操作名称
 * @param {number} [maxRetries=5] - 最大重试次数，默认为 5 次
 * @param {number} [retryDelay=3000] - 每次重试之间的延迟时间（毫秒），默认为 3000 毫秒
 * @returns {Promise<any>} 异步操作的结果
 */
async function withRetry(page, context, action, actionName, maxRetries = 5, retryDelay = 3000) {
  let retries = 0;
  const defaultActionName = actionName || '未命名操作';
  // 保存原始超时设置（如果可能）
  let originalTimeout = 30000; // 默认值
  try {
    // 检查getDefaultTimeout方法是否存在
    if (typeof page.getDefaultTimeout === 'function') {
      originalTimeout = page.getDefaultTimeout();
    }
  } catch (error) {
    // 忽略错误，使用默认值
  }
  
  // 设置更长的超时时间，特别是在headless模式下
  page.setDefaultTimeout(30000);
  
  while (retries < maxRetries) {
    try {
      sendLogToRenderer(`第 ${retries + 1} 次尝试执行操作: ${defaultActionName}`, 'info');
      const result = await action();
      // 操作成功后恢复原始超时设置
      try {
        page.setDefaultTimeout(originalTimeout);
      } catch (error) {
        // 忽略错误
      }
      return result;
    } catch (error) {
      retries++;
      
      // 检查是否为网络连接错误
      if (error.message.includes('net::ERR_NAME_NOT_RESOLVED')) {
        sendLogToRenderer('网络连接失败：无法解析域名', 'error');
        sendLogToRenderer('建议解决方案：请连接SGS VPN后重试', 'error');
        throw new Error('网络连接失败：无法解析域名，请连接SGS VPN后重试');
      } else if (error.message.includes('net::ERR_INTERNET_DISCONNECTED')) {
        sendLogToRenderer('网络连接失败：网络已断开', 'error');
        sendLogToRenderer('建议解决方案：请检查网络连接后重试', 'error');
        throw new Error('网络连接失败：网络已断开，请检查网络连接后重试');
      } else if (error.message.includes('net::ERR_CONNECTION_TIMED_OUT')) {
        sendLogToRenderer('网络连接失败：连接超时', 'error');
        sendLogToRenderer('建议解决方案：请检查网络连接或稍后重试', 'error');
        throw new Error('网络连接失败：连接超时，请检查网络连接或稍后重试');
      }
      
      if (retries === 1) {
        sendLogToRenderer(`${defaultActionName} 第 1 次尝试失败，即将刷新页面后重试...`, 'info');
        try {
          await page.reload(); 
        } catch (reloadError) {
          sendLogToRenderer(`页面刷新失败: ${reloadError.message}，继续重试操作`, 'warning');
        }
      }
      
      // 尝试多种策略解决元素被遮挡的问题
      try {
        // 1. 尝试滚动页面和处理遮挡元素
        await page.evaluate(() => {
          // 先滚动到顶部
          window.scrollTo(0, 0);
          
          // 然后滚动一点距离，避免顶部导航栏遮挡
          setTimeout(() => window.scrollTo(0, 100), 100);
          
          // 尝试隐藏可能遮挡的元素
          const possibleOverlays = [
            '.navbar-collapse', 
            '.collapse.navbar-collapse',
            '.modal',
            '.modal-backdrop',
            '.popover',
            '.dropdown-menu',
            '.tooltip',
            '.navbar-nav',
            '.navbar-header'
          ];
          
          possibleOverlays.forEach(selector => {
            const elements = document.querySelectorAll(selector);
            elements.forEach(el => {
              if (el && el.style) {
                el.style.display = 'none';
                el.style.pointerEvents = 'none';
                el.style.visibility = 'hidden';
                el.style.opacity = '0';
                el.style.zIndex = '-1';
              }
            });
          });
          
          // 特别处理可能的固定定位元素
          const fixedElements = document.querySelectorAll('[style*="position: fixed"], [style*="position:fixed"]');
          fixedElements.forEach(el => {
            if (el && el.style && el.getBoundingClientRect().top < 100) {
              el.style.display = 'none';
              el.style.pointerEvents = 'none';
            }
          });
        });
        
        // 2. 等待一段时间，让页面稳定
        await page.waitForTimeout(500);
        
        // 3. 尝试调整页面缩放和视口
        await page.evaluate(() => {
          document.body.style.zoom = '100%';
          document.documentElement.style.zoom = '100%';
        });
        
        // 4. 在无头模式下，尝试调整视口大小
        try {
          const viewport = page.viewportSize();
          if (viewport) {
            await page.setViewportSize({ width: Math.max(viewport.width, 1920), height: Math.max(viewport.height, 1080) });
          }
        } catch (viewportError) {
          // 忽略视口调整错误
        }
        
      } catch (scrollError) {
        // 忽略滚动错误
        sendLogToRenderer(`页面滚动或调整失败: ${scrollError.message}`, 'warning');
      }
      
      if (retries === maxRetries) {
        // 恢复原始超时设置
        try {
          page.setDefaultTimeout(originalTimeout);
        } catch (error) {
          // 忽略错误
        }
        throw new Error(`${defaultActionName}失败，已达到最大重试次数: ${error.message}`);
      }
      
      sendLogToRenderer(`${defaultActionName}第 ${retries} 次尝试失败，${retryDelay} 毫秒后进行第 ${retries + 1} 次重试...`, 'info');
      await new Promise((resolve) => setTimeout(resolve, retryDelay));
    }
  }
  
  // 恢复原始超时设置
  try {
    page.setDefaultTimeout(originalTimeout);
  } catch (error) {
    // 忽略错误
  }
  throw new Error(`未预期的重试逻辑结束，${defaultActionName} 失败`);
}

module.exports = { withRetry };